extends Node

#定义一个用户文件夹中存储文件的地址
var img_dir = OS.get_user_data_dir()+'/imgs/'

#随机生成uuid的工具变量
var uuid_util = preload("res://addon/uuid.gd")

## 设置文件
const SETTING_FILE = 'user://settings.ini'
# 创建两个变量
var setting_config_file = ConfigFile.new()
var settingData:SettingData = SettingData.new()
# 自动读取数据
var settings_loaded = false
# 数据发生变化之后进行更新保存
var setting_connected = false

### 版本文件
var FILE_VERSION_PATH = 'user://version.ini'
var version_file = null
# version比较的几种状态
enum VersionState{
	SAME,
	FORWARD,
	BACKWARD
}
var versionRequested:= false
var remoteVersionFile = null
## 技能数据文件
const ABILITY_FILE_PATH = 'user://ability.txt'
var ability_config_file = ConfigFile.new()
var ability_loaded = false

## 任务相关的变量以及文件
var milesyone_numbers = range(3,16)
var epoch_lengths = range(30,61,5)
const TASK_FILE_PATH = 'user://task.txt'
var task_config_file = ConfigFile.new()
var task_loaded = false

## 日程文件以及日程相关的变量
const SCHEDULE_FILE_PATH = 'user://schedule.txt'
var schedule_config_file = ConfigFile.new()
var schedule_loaded = false
# 字典 date:{period: schedule_list}
var date_period_schedules = {}
var date_period_length = {}
var date_schedule_loaded = false
var schedule_lengths_stated = false
# 各时段长度
var period_time_zone_length = {
	1: 180,
	2: 180,
	3: 180,
	4: 120
}
# schedule的几种状态
enum ScheduleState {
	UNPROCESSED, # 待处理, 当天需要处理的
	FINISHED, # 已完成， 今天或者之前已经完成的
	DELAYED, # delayed， 标记为delayed
	UNFINISHED, # 未完成，过了日期之后自动未完成
	UNSTARTED
}

### ==== 创建一个action history, 记录action和对应的页面
var action_history:Array[ActionData]

## 数据同步的requests
var validate_http_request = HTTPRequest.new()
var upload_http_request = HTTPRequest.new()
var download_http_request = HTTPRequest.new()
var version_http_request = HTTPRequest.new()


#NOTIFICATION
enum NOTIFICATION_TYPE {
	INFO,
	ERROR,
	WARNING
}

## 版本更新的timer
var async_gap_timer = Timer.new()

#初始化函数
func _init():
	create_img_dir()
	#初始化各种requests
	init_requests()
	#加载各个配置文件及存储数据文件
	load_config_files()
	# 监听该文件变化
	listenFileChanged()
	# 更新async_gap_timer
	init_async_gap_timer()

func _ready():
	#fetch_remote_versions()
	# 如果有网盘数据，就进行同步
	async_data()

func create_img_dir():
	if not DirAccess.dir_exists_absolute(img_dir):
		DirAccess.make_dir_recursive_absolute(img_dir)

func fetch_remote_versions():
	if settingData.webdavValidated:
		send_version_request()

# 监听文件改变的事件
func listenFileChanged():
	## 监听几个file改变的信号, 更新version的时间
	Signalbus.file_changed.connect(_on_file_changed)
	# 比较服务器版本的
	Signalbus.version_compare_completed.connect(_on_version_compare_completed)
	# 日程完成之后
	Signalbus.schedule_finished.connect(_on_schedule_finished)
	# 日程重新规划请求，主要是action页面延迟到明天调用
	Signalbus.schedule_arrange_request.connect(_on_schedule_arrange_requested)
	# 任务手动保存之后,上传数据
	Signalbus.task_added.connect(start_to_async)
	Signalbus.task_deled.connect(start_to_async)
	Signalbus.task_finished.connect(start_to_async)
	#完成保存之后上传数据
	Signalbus.schedules_arranged.connect(start_to_async)
	Signalbus.ability_file_changed.connect(start_to_async)

# async_gap_timer结束后才能够进行更新
func init_async_gap_timer():
	async_gap_timer.autostart = false
	async_gap_timer.one_shot = true
	add_child(async_gap_timer)
	async_gap_timer.timeout.connect(async_data)
	
func start_to_async(_data = null):
	async_gap_timer.start(0.5)

func _on_schedule_arrange_requested(taskID:String):
	var taskEn = load_task(taskID)
	GlobalUtil.arrange_task_schedules(taskEn)
	#update_version_time()

func _on_schedule_finished(scheduleData:ScheduleData):
	# 日程完成之后
	# 首先更新任务的状态
	var taskEn:TaskEntity = load_task(scheduleData.related_task)
	taskEn.hours_used += scheduleData.length/float(60)
	taskEn.subtasks[scheduleData.related_subtask_seqno].subtask_hours_used += scheduleData.length/float(60)
	var related_ability = get_ability(taskEn.related_ability)
	related_ability.hours += scheduleData.actual_length/float(60)/float(60)
	save_task(taskEn)
	save_ability_directly(related_ability)
	start_to_async()

func _on_file_changed(filename:String):
	update_file_version_time(filename)

# 初始用于同步的httpRequest
func init_requests():
	add_child(validate_http_request)
	add_child(upload_http_request)
	add_child(download_http_request)
	add_child(version_http_request)
	validate_http_request.request_completed.connect(_on_validated)
	download_http_request.request_completed.connect(_on_download_completed)
	version_http_request.request_completed.connect(_on_version_request_completed)
	Signalbus.version_compare_request.connect(_on_version_compare_requested)

func load_config_files():
	# 自动读取数据
	settings_loaded = load_setting_data()
	settingData.changed.connect(_on_setting_data_changed)
	GlobalUtil.set_resolution(settingData.resolution)
	
	# 加载三种该数据文件
	ability_loaded = load_ability_file()
	task_loaded = load_task_file()
	schedule_loaded = load_schedule_file()
	
	# 加载schedule数据
	date_schedule_loaded = load_all_schedules()
	schedule_lengths_stated = stat_schedule_length()
	
	#version load
	load_version_file()


#####=========================
##### version file的各种操作
####==========================
func load_version_file():
	version_file = ConfigFile.new()
	version_file.clear()
	version_file.load(FILE_VERSION_PATH)
	#判断比较两个是否一致，然后进行更新
	update_basic_files()
	#update_img_files()

func save_version_file():
	version_file.save(FILE_VERSION_PATH)

func update_version_time():
	version_file.set_value('time','last',Time.get_unix_time_from_system())
	save_version_file()

func update_file_version_time(filename):
	var time = int(Time.get_unix_time_from_system())
	version_file.set_value('time',filename,time)
	version_file.set_value('time','last',time)
	save_version_file()

func get_version_time():
	return version_file.get_value('time','last',0)

func get_remote_version_time():
	return remoteVersionFile.get_value('time','last',0)

func get_file_version_time(filename:String):
	return version_file.get_value('time',filename,0)

func get_file_remote_version_time(filename:String):
	return remoteVersionFile.get_value('time',filename,0)

func update_basic_files():
	# TODO 仅测试使用
	var basic_files = [FILE_VERSION_PATH, ABILITY_FILE_PATH, TASK_FILE_PATH, SCHEDULE_FILE_PATH, SETTING_FILE]
	if basic_files != version_file.get_value('file','basic',[]):
		version_file.set_value('file','basic',basic_files)
		save_version_file()

func get_basic_files():
	return version_file.get_value('file','basic')

func get_remote_basic_files():
	return remoteVersionFile.get_value('file','basic')

func update_img_files():
	if get_files_in_imgs()!=version_file.get_value('file','img',[]):
		version_file.set_value('file','img',get_files_in_imgs())
		save_version_file()
	
	#for img_path in get_img_files():
		#GlobalVariables.update_file_version_time(img_path.get_file())

func update_img_file(imgfilename:String):
	var imgs = get_img_files()
	if imgfilename not in imgs:
		imgs.append(imgfilename)
	version_file.set_value('file','img',imgs)
	save_version_file()

func get_img_files():
	return version_file.get_value('file','img',[])

func get_remote_img_files():
	return remoteVersionFile.get_value('file','img',[])
	
#####=========================
##### 技能数据的各种操作
####==========================
func load_ability_file():
	ability_config_file.clear()
	ability_config_file.load(ABILITY_FILE_PATH)

func save_ability_file():
	ability_config_file.save(ABILITY_FILE_PATH)
	Signalbus.ability_file_changed.emit()
	Signalbus.file_changed.emit(ABILITY_FILE_PATH.get_file())

#或的了所有的技能id
func get_all_ability_keys():
	if not ability_loaded:
		ability_loaded = load_ability_file()
	return ability_config_file.get_section_keys('ability')

func get_ability(id:String):
	if not ability_loaded:
		ability_loaded = load_ability_file()
	return ability_config_file.get_value('ability',id)

# 完成了修改添加的功能
func add_ability(ability_data:AbilityEntity):
	# 首先尝试获取这一条
	var exists_abilty = get_ability(ability_data.id)
	#当查询到已有记录的时候，就说明这个是修改技能
	
	# 更新当前父类数据
	if ability_data.parent_id != 'NULL':
		var parent_data:AbilityEntity = get_ability(ability_data.parent_id)
		if not ability_data.id in parent_data.children_id:
			parent_data.children_id.append(ability_data.id)
			ability_config_file.set_value('ability',ability_data.parent_id,parent_data)
	
	if exists_abilty != null:
		# 首先判断之前的parent_id和当前parent_id不一样
		if exists_abilty.parent_id != ability_data.parent_id:
			# 并不是根技能
			if exists_abilty.parent_id !='NULL':
				erase_from_parent(ability_data.id,exists_abilty.parent_id)
	
	#保存这一条数据
	if exists_abilty!=null:
		ability_data.children_id = exists_abilty.children_id
	ability_config_file.set_value('ability',ability_data.id,ability_data)

func save_ability_directly(abilityEn:AbilityEntity):
	ability_config_file.set_value('ability',abilityEn.id,abilityEn)
	save_ability_file()

func del_ability(ability_data:AbilityEntity):
	# 删除父类中的记录
	erase_from_parent(ability_data.id,ability_data.parent_id)
	# 循环删除
	del_all_children(ability_data)

func del_all_children(ability_data):
	#当前自己删掉
	ability_config_file.erase_section_key('ability',ability_data.id)
	var children_id_list  = ability_data.children_id
	if children_id_list.size()>0:
		for child_id in children_id_list:
			var child_data = get_ability(child_id)
			del_all_children(child_data)
	

func erase_from_parent(current_id:String,parent_id:String):
	var parent_data:AbilityEntity = get_ability(parent_id)
	if parent_data == null:
		return
	# 从之前的children_id里面给删除掉
	parent_data.children_id.erase(current_id)
	ability_config_file.set_value('ability',parent_data.id,parent_data)


#####=========================
##### 任务数据的各种操作
####==========================
func load_task_file():
	task_config_file.clear()
	task_config_file.load(TASK_FILE_PATH)
	return true

func save_task_file():
	task_config_file.save(TASK_FILE_PATH)
	Signalbus.task_file_changed.emit()
	Signalbus.file_changed.emit(TASK_FILE_PATH.get_file())

func load_all_tasks()->Array[TaskEntity]:
	if not task_loaded:
		task_loaded = load_task_file()
	var tasks:Array[TaskEntity] = []
	for tid in task_config_file.get_section_keys('task'):
		tasks.append(load_task(tid))
	return tasks

func save_task(taskEn:TaskEntity):
	task_config_file.set_value('task',taskEn.tid,taskEn)
	save_task_file()

func load_task(task_id:String)->TaskEntity:
	return task_config_file.get_value('task',task_id)

func load_test_task_demo():
	load_task_file()
	var task_ids = task_config_file.get_section_keys('task')
	if len(task_ids)>0:
		return task_config_file.get_value('task',task_ids[0])
	else:
		return null
	
func del_task(task:TaskEntity):
	task.isNormal = false
	save_task(task)

# 删除所有任务相关的删除schedule
func del_related_schedules():
	for task_id in task_config_file.get_section_keys('task'):
		var task:TaskEntity = task_config_file.get_value('task',task_id)
		for subtask in task.subtasks:
			subtask.related_schedules = []
		save_task(task)

func get_ability_parents(ability:AbilityEntity)->Array[AbilityEntity]:
	var abilities:Array[AbilityEntity] = []
	abilities.append(ability)
	var parent_id = ability.parent_id
	if parent_id == 'NULL':
		return abilities
	else:
		var parent_ability = get_ability(parent_id)
		abilities.append_array(get_ability_parents(parent_ability))
		return abilities

#####=========================
##### 日程相关操作
####==========================
func load_schedule_file():
	schedule_config_file.clear()
	schedule_config_file.load(SCHEDULE_FILE_PATH)
	return true

func save_schedule_file():
	schedule_config_file.save(SCHEDULE_FILE_PATH)
	Signalbus.schedule_file_changed.emit()
	Signalbus.file_changed.emit(SCHEDULE_FILE_PATH.get_file())

func save_schedule(schedule_data:ScheduleData,with_save=true):
	schedule_config_file.set_value('schedule',schedule_data.schedule_id,schedule_data)
	update_schdules_in_memory(schedule_data)
	if with_save:
		save_schedule_file()

func save_schedules(schedule_datas:Array[ScheduleData]):
	for schedule_data in schedule_datas:
		schedule_config_file.set_value('schedule',schedule_data.schedule_id,schedule_data)
	save_schedule_file()

func del_schedule(schedule_id:String,with_save=true):
	schedule_config_file.erase_section_key('schedule',schedule_id)
	if with_save:
		save_schedule_file()

func del_schedules(schedule_id_list:Array[String]):
	for schedule_id in schedule_id_list:
		del_schedule(schedule_id,false)
	save_schedule_file()

func del_all_schedule():
	schedule_config_file.erase_section('schedule')
	save_schedule_file()

func del_task_schedules(taskID:String):
	var task = load_task(taskID)
	for schedule_id in schedule_config_file.get_section_keys('schedule'):
		var scheduleData = get_schedule_data(schedule_id)
		var state = check_schedule_state(scheduleData)
		
		if scheduleData.related_task != taskID:
			continue
		
		if scheduleData.related_subtask_seqno >= task.subtasks.size():
			del_schedule(schedule_id,true)
			continue
			
		var subtask = task.subtasks[scheduleData.related_subtask_seqno]
		
		if state == ScheduleState.UNPROCESSED and GlobalVariables.settingData.doScheduleFromToday:
			del_schedule(schedule_id,false)
			subtask.related_schedules.erase(schedule_id)
		
		if state == ScheduleState.UNSTARTED:
			del_schedule(schedule_id,false)
			subtask.related_schedules.erase(schedule_id)
		
		task.subtasks[scheduleData.related_subtask_seqno] = subtask
	save_task(task)
			
	save_schedule_file()
	load_all_schedules()
	stat_schedule_length()

func del_subtask_schedules(subtaskEn:SubtaskEntity):
	for schedule_id in subtaskEn.related_schedules.duplicate():
		var scheduleData = get_schedule_data(schedule_id)
		var state = check_schedule_state(scheduleData)
		
		if state == ScheduleState.UNPROCESSED and GlobalVariables.settingData.doScheduleFromToday:
			del_schedule(schedule_id,false)
		if state == ScheduleState.UNSTARTED:
			del_schedule(schedule_id,false)
			
	save_schedule_file()
	load_all_schedules()
	stat_schedule_length()

func load_all_schedules():
	date_period_schedules.clear()
	for schedule_id in schedule_config_file.get_section_keys('schedule'):
		var scheduleData = schedule_config_file.get_value('schedule',schedule_id,null)
		update_schdules_in_memory(scheduleData)
	return true

func get_schedule_data(scheduleID:String)->ScheduleData:
	if not schedule_loaded:
		schedule_loaded = load_schedule_file()
		
	return schedule_config_file.get_value('schedule',scheduleID,null)

func stat_schedule_length():	
	date_period_length.clear()
	for date in date_period_schedules.keys():
		for period in date_period_schedules[date].keys():
			var length = 0 
			var period_length = date_period_length.get(date,{})
			for schedule_id in date_period_schedules[date][period]:
				var schedule = get_schedule_data(schedule_id)
				var state = check_schedule_state(schedule)
				if state == ScheduleState.UNPROCESSED or state == ScheduleState.UNSTARTED or state == ScheduleState.FINISHED:
					length += schedule.length
			period_length[period] = length
			date_period_length[date]= period_length
	return true

func update_task_related_schedules(scheduleData:ScheduleData):
	var taskID = scheduleData.related_task
	var taskEn = load_task(taskID)
	var subtask = taskEn.subtasks[scheduleData.related_subtask_seqno]
	subtask.related_schedules.append(scheduleData.schedule_id)
	save_task(taskEn)

func update_schdules_in_memory(scheduleData:ScheduleData):
	#if check_schedule_state(scheduleData) == ScheduleState.FINISHED or check_schedule_state(scheduleData) == ScheduleState.DELAYED:
		#update_task_related_schedules(scheduleData)
	
	var date = scheduleData.schedule_date
	var period = scheduleData.working_period
	var period_schedules = date_period_schedules.get(date,{})
	var schedules = period_schedules.get(period,[])
	if not scheduleData.schedule_id in schedules:
		schedules.append(scheduleData.schedule_id)
		period_schedules[period] = schedules
		date_period_schedules[date]= period_schedules
		schedule_lengths_stated = false
	

# 判断对应日期以及时间段有没有足够的空间添加这个时间长度
func check_time_space(date:String, period:int, timeLengthToAdded:int)->bool:
	
	if not schedule_lengths_stated:
		schedule_lengths_stated = stat_schedule_length()
		
	var period_length = date_period_length.get(date,{})
	var lengthOccupied = period_length.get(period,0)
	#print(date,'==',period,'==',timeLengthToAdded,'==',period_length)

	if lengthOccupied+timeLengthToAdded <= period_time_zone_length[period]:
		return true
	return false

# 删除子任务关联的今天及以后得所有日程
func del_subtask_unfinished_schedules(subtask:SubtaskEntity):
	var schedules = subtask.related_schedules.duplicate()
	for schedule_id in schedules:
		var scheduleData = get_schedule_data(schedule_id)
		var state = check_schedule_state(scheduleData)
		
		if state == ScheduleState.UNPROCESSED and GlobalVariables.settingData.doScheduleFromToday:
			del_schedule(scheduleData.schedule_id,false)
			subtask.related_schedules.erase(scheduleData.schedule_id)
		
		if state == ScheduleState.UNSTARTED:
			del_schedule(scheduleData.schedule_id,false)
			subtask.related_schedules.erase(scheduleData.schedule_id)
			
	# 删除之后需要重新加载统计数据
	load_all_schedules()
	stat_schedule_length()
	save_schedule_file()
	

# 接口完成日程的添加
func assign_schedule_by_subtask(subtaskEn:SubtaskEntity, start_date:Calendar.Date, \
	prefered_periods:Array[int], epoch_length:int, epoch_num:int, taskID:String, \
	subtaskSeqNo:int, working_days:Array[int],epoch_added_today=0):
	
	var schedules:Array[ScheduleData] = []
	var schedule_ids:Array[String] = []
	
	# 这个就是子任务一共需要创建的epoch_nums
	var epoch_nums  = int(ceil(float(subtaskEn.subtask_hours - subtaskEn.subtask_hours_used)/(epoch_length/float(60))))
	var iteration_max = 0
	while schedules.size() < epoch_nums:
		for i in range(epoch_num-epoch_added_today):
			var weekdayno = start_date.duplicate().get_weekday_iso() # 1-7
			#print('%d/%02d/%02d' % [start_date.year,start_date.month,start_date.day])
			if not weekdayno in working_days:
				start_date.add_days(1)
				break
			#判断这个日期是否有足够的空间添加这个日程
			var has_enough_space_in_prefered_periods = false
			for period in prefered_periods:
				if check_time_space(format_date(start_date), period, epoch_length):
					# 添加日程
					# 根据子任务的开始时间，子任务的长度，任务的偏好时段，任务的单节长度, 每天工作节数进行判断规划
					var scheduleData = ScheduleData.new()
					scheduleData.init("S_"+uuid_util.v4(), format_date(start_date), false, subtaskEn.name, taskID, \
						subtaskSeqNo, epoch_length, 0, period,subtaskEn.related_files)
						
					schedules.append(scheduleData)
					schedule_ids.append(scheduleData.schedule_id)
					has_enough_space_in_prefered_periods = true
					save_schedule(scheduleData,false)
					epoch_added_today+=1
					break
			
			if not has_enough_space_in_prefered_periods:
				# TODO 所有的日程都没有时间，应该怎么办
				iteration_max +=1
				push_error('没有足够时间')
				return [[],start_date,false]
			
			# 防止死循环
			if iteration_max>10:
				break
			
			if schedules.size() == epoch_nums:
				break
				
		if epoch_added_today >= epoch_num:
			start_date.add_days(1)
			epoch_added_today=0
	#保存这个任务的所有schedule
	save_schedules(schedules)
	
	return [schedule_ids, start_date,epoch_added_today]

func check_schedule_state(scheduleData:ScheduleData)-> ScheduleState:
	if scheduleData.is_finished:
		return ScheduleState.FINISHED
	else:
		if scheduleData.is_delayed:
			return ScheduleState.DELAYED
		else:
			var scheduleDate = time_str_2_date(scheduleData.schedule_date)
			var today = get_current_date()
			if scheduleDate.is_before(today):
				return ScheduleState.UNFINISHED
			elif scheduleDate.is_equal(today):
				return ScheduleState.UNPROCESSED
			elif scheduleDate.is_after(today):
				return ScheduleState.UNSTARTED
			else:
				return ScheduleState.UNPROCESSED


#####=========================
##### 日期相关操作
####==========================
var cal: Calendar = Calendar.new()
func get_current_date()->Calendar.Date:
	return Calendar.Date.today()

func time_str_2_date(timeStr:String)->Calendar.Date:
	var splits = timeStr.split('/')
	return Calendar.Date.new(int(splits[0]),int(splits[1]),int(splits[2]))

func format_date(date:Calendar.Date)->String:
	return '%d/%02d/%02d' % [date.year,date.month,date.day]


#####=========================
##### 设置文件的相关操作
####==========================
func load_setting_file():
	setting_config_file.clear()
	if not FileAccess.file_exists(SETTING_FILE):
		save_setting_file()
	setting_config_file.load(SETTING_FILE)

func save_setting_file():
	setting_config_file.set_value('settings','general',settingData)
	setting_config_file.save(SETTING_FILE)
	Signalbus.setting_file_changed.emit()
	Signalbus.file_changed.emit(SETTING_FILE.get_file())

func load_setting_data()->bool:
	settings_loaded = load_setting_file()
	var loadedSettingData = setting_config_file.get_value('settings','general',null)
	if loadedSettingData !=null:
		settingData = loadedSettingData
	return true
	
func _on_setting_data_changed():
	save_setting_file()
	# 数据发生变化的时候进行更改
	GlobalUtil.set_resolution(settingData.resolution)
	

## WEBDAV 同步的方法
func generateAuthHeader(username:String, password:String):
	return 'Basic '+ Marshalls.utf8_to_base64(username+":"+password)


func validate_webdav():
	if GlobalVariables.settingData.webdavServerURL=='':
		return false
	if GlobalVariables.settingData.webdavRemoteFolderPath=="":
		return false
	if GlobalVariables.settingData.webdavUsernamme =="":
		return false
	if GlobalVariables.settingData.webdavPassword == "":
		return false
	
	return true

func send_validate_request():
	
	if not validate_webdav():
		GlobalUtil.send_notification("网盘同步数据未设置或者设置错误！")
		return 
	
	var file = FileAccess.open('res://icon.png',FileAccess.READ)
	var content = file.get_buffer(file.get_length())
	file.close()
	var url = GlobalVariables.settingData.webdavServerURL+GlobalVariables.settingData.webdavRemoteFolderPath+'icon.png'
	var headers = ['Authorization:'+generateAuthHeader(GlobalVariables.settingData.webdavUsernamme,GlobalVariables.settingData.webdavPassword)]
	#validate_http_request.request_completed.connect(_http_request_completed)
	validate_http_request.request_raw(url,headers,HTTPClient.METHOD_PUT,content)

func _on_validated(_result, response_code, _headers, _body):
	if response_code in [200, 201, 204]:
		GlobalVariables.settingData.webdavValidated = true
		Signalbus.webdav_server_validated.emit(true)
	else:
		GlobalVariables.settingData.webdavValidated = false
		Signalbus.webdav_server_validated.emit(false)

#####=========================
##### 数据同步的操作
####==========================
var download_index = 0
var is_downing_img = false
func read_file_buffer(path:String):
	var file = FileAccess.open(path,FileAccess.READ)
	var content = file.get_buffer(file.get_length())
	file.close()
	return content

func get_files_in_imgs()->Array[String]:
	var img_files:Array[String] = []
	for filename in DirAccess.get_files_at(img_dir):
		img_files.append('user://imgs/'+filename)
	return img_files

func send_upload_request():
	var baseurl = GlobalVariables.settingData.webdavServerURL+GlobalVariables.settingData.webdavRemoteFolderPath
	var headers = ['Authorization:'+generateAuthHeader(GlobalVariables.settingData.webdavUsernamme,GlobalVariables.settingData.webdavPassword)]
	update_img_files()
	
	send_version_request()
	await Signalbus.version_file_downloaded
	
	if remoteVersionFile == null and GlobalVariables.settingData.webdavValidated:
		GlobalUtil.send_notification('远程库为空！')
		remoteVersionFile = ConfigFile.new()
	
	var file_changed_count = 0
	
	for filename in get_basic_files():
		if upload_http_request.is_processing():
			await upload_http_request.request_completed
		#if get_file_version_time(filename.get_file()) > get_file_remote_version_time(filename.get_file()) \
		#or (filename.get_file() == 'version.ini' and get_version_time() > get_remote_version_time()):
		var url = baseurl+filename.get_file()
		#var filepath = OS.get_user_data_dir()+'/'+filename.get_file()
		upload_http_request.request_raw(url,headers,HTTPClient.METHOD_PUT,read_file_buffer(filename))
		await upload_http_request.request_completed
		file_changed_count+=1
	
	for imgfile in get_img_files():
		if get_file_version_time(imgfile.get_file()) > get_file_remote_version_time(imgfile.get_file()):
			var url = baseurl+'IMG_'+imgfile.get_file()
			upload_http_request.request_raw(url,headers,HTTPClient.METHOD_PUT,read_file_buffer(imgfile))
			await upload_http_request.request_completed
			file_changed_count+=1
			
	Signalbus.file_uploaded.emit()
	if file_changed_count >0:
		GlobalUtil.send_notification('%d个文件已上传!'%file_changed_count)

func send_download_request():
	var baseurl = GlobalVariables.settingData.webdavServerURL+GlobalVariables.settingData.webdavRemoteFolderPath
	var headers = ['Authorization:'+generateAuthHeader(GlobalVariables.settingData.webdavUsernamme,GlobalVariables.settingData.webdavPassword)]
	
	send_version_request()
	await Signalbus.version_file_downloaded
	
	if remoteVersionFile == null:
		GlobalUtil.send_notification('远程库为空！')
		return
	
	var file_download_count = 0
	# 需要比较上传和下载的文件时间戳
	#version_file = remoteVersionFile
	download_index = 0
	is_downing_img = false
	#下载的时候需要根据远程的文件列表进行
	for filename in get_remote_basic_files():
		# 比较时间 如果本地时间比远程更改时间靠后，就不进行下载, 主要目的就是为了不重复下载文件
		#if get_file_version_time(filename.get_file()) < get_file_remote_version_time(filename.get_file()):
		var url = baseurl+filename.get_file()
		download_http_request.request_raw(url,headers,HTTPClient.METHOD_GET)
		await download_http_request.request_completed
		file_download_count += 1
		download_index+=1
	
	download_index = 0
	is_downing_img = true
	for imgfile in get_remote_img_files():
		# 比较时间 如果本地时间比远程更改时间靠后，就不进行下载
		if get_file_version_time(imgfile.get_file()) < get_file_remote_version_time(imgfile.get_file()):
			var url = baseurl+'IMG_'+imgfile.get_file()
			download_http_request.request_raw(url,headers,HTTPClient.METHOD_GET)
			await download_http_request.request_completed
			file_download_count += 1
		download_index+=1
		
	#覆盖为远程File
	version_file = remoteVersionFile
	save_version_file()
	Signalbus.file_downloaded.emit()
	_reload_all_files()
	var msg = '%d个文件已下载!'%file_download_count
	if file_download_count > 0:
		GlobalUtil.send_notification(msg)
	else:
		GlobalUtil.send_notification('无数据变动!')
	
func _on_download_completed(_result, response_code, _headers, body):
	if response_code in [200, 201, 204]:
		var filename =''
		if is_downing_img:
			var file = FileAccess.open(get_remote_img_files()[download_index],FileAccess.WRITE)
			file.store_buffer(body)
			file.close()
		else:
			filename = get_remote_basic_files()[download_index]
			var file = FileAccess.open(filename,FileAccess.WRITE)
			file.store_buffer(body)
			file.close()

func send_version_request():
	var baseurl = GlobalVariables.settingData.webdavServerURL+GlobalVariables.settingData.webdavRemoteFolderPath
	var headers = ['Authorization:'+generateAuthHeader(GlobalVariables.settingData.webdavUsernamme,GlobalVariables.settingData.webdavPassword)]
	var url = baseurl+FILE_VERSION_PATH.get_file()
	version_http_request.request_raw(url,headers,HTTPClient.METHOD_GET)

func send_version_compare():
	send_version_request()
	await Signalbus.version_file_downloaded
	if remoteVersionFile == null:
		Signalbus.version_compare_completed.emit(VersionState.FORWARD)
		return
	var remoteTime = get_remote_version_time()
	var currentTime = get_version_time()
	#print(remoteTime,'->',currentTime)
	if currentTime == remoteTime:
		Signalbus.version_compare_completed.emit(VersionState.SAME)
	elif currentTime > remoteTime:
		Signalbus.version_compare_completed.emit(VersionState.FORWARD)
	else:
		Signalbus.version_compare_completed.emit(VersionState.BACKWARD)

func _on_version_request_completed(_result, response_code, _headers, body):
	if response_code == 404:
		remoteVersionFile = null
		#Signalbus.version_file_downloaded.emit()
	else:
		if remoteVersionFile == null:
			remoteVersionFile = ConfigFile.new()
			
		remoteVersionFile.clear()
		remoteVersionFile.parse(body.get_string_from_utf8())
		#remoteVersionFile = versionFile
		versionRequested = true
	
	Signalbus.version_file_downloaded.emit()

func _on_version_compare_completed(state:VersionState):
	match state:
		VersionState.SAME:
			GlobalUtil.send_notification('本地数据与服务器一致！')
		VersionState.FORWARD:
			send_upload_request()
		VersionState.BACKWARD:
			send_download_request()

func async_data(_data=null):
	# 比较版本
	send_validate_request()
	await Signalbus.webdav_server_validated
	#如果验证了服务器，直接上传
	if GlobalVariables.settingData.webdavValidated:
		GlobalVariables.send_version_compare()
	else:
		GlobalUtil.send_notification('服务器验证错误！')

func _on_version_compare_requested():
	send_version_request()
#
func _reload_all_files():
	load_version_file()
	load_setting_data()
	load_ability_file()
	load_task_file()
	load_schedule_file()
	load_all_schedules()
	stat_schedule_length()


